package com.dailyblue.java.standard.design;

import com.dailyblue.java.standard.design.单例模式.单例模式1;
import com.dailyblue.java.standard.design.单例模式.单例模式2;
import com.dailyblue.java.standard.design.单例模式.单例模式3;
import com.dailyblue.java.standard.design.单例模式.单例模式4;
import com.dailyblue.java.standard.design.策略模式.ChaseGirlsStrategy;
import com.dailyblue.java.standard.design.策略模式.Context;
import com.dailyblue.java.standard.design.策略模式.Strategy;
import com.dailyblue.java.standard.design.策略模式.StudyStrategy;
import com.dailyblue.java.standard.design.装饰者模式.Decorater;
import com.dailyblue.java.standard.design.装饰者模式.Person;
import com.dailyblue.java.standard.design.装饰者模式.Programmer;
import com.dailyblue.java.standard.design.装饰者模式.Sing;
import com.dailyblue.java.standard.design.观察者模式.LotteryObServer;
import com.dailyblue.java.standard.design.观察者模式.LotterySubject;
import com.dailyblue.java.standard.design.观察者模式.ObServer;
import com.dailyblue.java.standard.design.观察者模式.Subject;
import com.dailyblue.java.standard.design.责任链模式.CTOHandler;
import com.dailyblue.java.standard.design.责任链模式.GroupLeaderHandler;
import com.dailyblue.java.standard.design.责任链模式.Handler;
import com.dailyblue.java.standard.design.责任链模式.ProjectManagerHandler;
import com.dailyblue.java.standard.design.适配器模式.Phone;
import com.dailyblue.java.standard.design.适配器模式.PhoneAdapter;
import com.dailyblue.java.standard.design.适配器模式.Power;

import java.lang.reflect.Constructor;

public class App {

    public static void a() {
        单例模式1 dl1 = 单例模式1.getInstance();
        单例模式1 dl2 = 单例模式1.getInstance();
        System.out.println(dl1);
        System.out.println(dl2);
        System.out.println(dl1 == dl2);
    }

    public static void b() {
        单例模式2 dl1 = 单例模式2.getInstance();
        单例模式2 dl2 = 单例模式2.getInstance();
        System.out.println(dl1);
        System.out.println(dl2);
        System.out.println(dl1 == dl2);
    }

    // 一个问题
    public static void c() {
        final 单例模式3[] dl = new 单例模式3[2];
        // 这个线程调用了获取对象的方法
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                dl[0] = 单例模式3.getInstance();
            }
        });
        // 这个线程调用了获取对象的方法
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                dl[1] = 单例模式3.getInstance();
            }
        });
        t1.start();
        t2.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(dl[0]);
        System.out.println(dl[1]);
        System.out.println(dl[0] == dl[1]);
    }

    // 另一个问题 反射可以访问私有内容 怎么办？
    public static void d() throws Exception {
        Class c = Class.forName("com.dailyblue.java.standard.design.单例模式.单例模式1");
        Constructor c1 = c.getDeclaredConstructor();
        Constructor c2 = c.getDeclaredConstructor();
        c1.setAccessible(true);
        c2.setAccessible(true);
        Object obj1 = c1.newInstance();
        Object obj2 = c2.newInstance();
        System.out.println(obj1);
        System.out.println(obj2);
        System.out.println(obj1 == obj2);
    }

    public static void e() {
        单例模式4 dl1 = 单例模式4.INSTANCE;
        单例模式4 dl2 = 单例模式4.INSTANCE;
        System.out.println(dl1);
        System.out.println(dl2);
        System.out.println(dl1 == dl2);
        dl1.a();
        dl2.a();
    }

    public static void f() {
        Power power = new Power();
        Phone phone = new Phone();
        PhoneAdapter adapter = new PhoneAdapter(power);
        phone.charge(adapter);
    }

    public static void g() {
        Strategy strategy = new StudyStrategy();
        Context context = new Context(strategy);
        context.strategy();
    }

    public static void h() {
        Handler gl = new GroupLeaderHandler();
        Handler pm = new ProjectManagerHandler();
        Handler cto = new CTOHandler();
        gl.setNextHandler(pm);
        pm.setNextHandler(cto);
        System.out.println("请假20天");
        gl.handle(3);
    }

    public static void i() {
        Person p1 = new Programmer();
        Decorater d1 = new Sing(p1);
        d1.setName("张三");
        d1.action();
    }

    public static void j() {
        // 彩票主题
        Subject subject = new LotterySubject();
        for (int i = 1; i < 21; i++) {
            ObServer ob = new LotteryObServer(i);
            // 将彩民注册到彩票站的通知中
            subject.registerObServer(ob);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        subject.advice();
    }

    public static void main(String[] args) throws Exception {
        j();
    }
}
